﻿using System;
using System.Collections.Generic;
using GeoAPI.Geometries;
using NetTopologySuite.Noding;

namespace NetTopologySuite.Geometries.Prepared
{
	internal abstract class AbstractPreparedPolygonContains : PreparedPolygonPredicate
	{
		protected AbstractPreparedPolygonContains(PreparedPolygon prepPoly) : base(prepPoly)
		{
		}

		protected bool Eval(IGeometry geom)
		{
			if (!base.IsAllTestComponentsInTarget(geom))
			{
				return false;
			}
			if (this.RequireSomePointInInterior && geom.Dimension == Dimension.Point)
			{
				return base.IsAnyTestComponentInTargetInterior(geom);
			}
			bool flag = this.IsProperIntersectionImpliesNotContainedSituation(geom);
			this.FindAndClassifyIntersections(geom);
			if (flag && this._hasProperIntersection)
			{
				return false;
			}
			if (this._hasSegmentIntersection && !this._hasNonProperIntersection)
			{
				return false;
			}
			if (this._hasSegmentIntersection)
			{
				return this.FullTopologicalPredicate(geom);
			}
			return !(geom is IPolygonal) || !base.IsAnyTargetComponentInAreaTest(geom, this.prepPoly.RepresentativePoints);
		}

		private bool IsProperIntersectionImpliesNotContainedSituation(IGeometry testGeom)
		{
			return testGeom is IPolygonal || AbstractPreparedPolygonContains.IsSingleShell(this.prepPoly.Geometry);
		}

		private static bool IsSingleShell(IGeometry geom)
		{
			return geom.NumGeometries == 1 && ((IPolygon)geom.GetGeometryN(0)).NumInteriorRings == 0;
		}

		private void FindAndClassifyIntersections(IGeometry geom)
		{
			IList<ISegmentString> segStrings = SegmentStringUtil.ExtractSegmentStrings(geom);
			SegmentIntersectionDetector segmentIntersectionDetector = new SegmentIntersectionDetector();
			segmentIntersectionDetector.FindAllIntersectionTypes = true;
			this.prepPoly.IntersectionFinder.Intersects(segStrings, segmentIntersectionDetector);
			this._hasSegmentIntersection = segmentIntersectionDetector.HasIntersection;
			this._hasProperIntersection = segmentIntersectionDetector.HasProperIntersection;
			this._hasNonProperIntersection = segmentIntersectionDetector.HasNonProperIntersection;
		}

		protected abstract bool FullTopologicalPredicate(IGeometry geom);

		protected bool RequireSomePointInInterior = true;

		private bool _hasSegmentIntersection;

		private bool _hasProperIntersection;

		private bool _hasNonProperIntersection;
	}
}
